package net.realsee.service.wcs.work.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import net.realsee.common.enums.wcs.order.OrderStatusEnums;
import net.realsee.common.enums.wcs.order.OrderTypeEnums;
import net.realsee.common.exception.ServiceException;
import net.realsee.common.utils.StringUtils;
import net.realsee.common.utils.spring.SpringUtils;
import net.realsee.domain.wcs.rcs.hik.HikRcsOperateResult;
import net.realsee.domain.wcs.work.WcsOrderHeader;
import net.realsee.domain.wcs.work.bo.WcsOrderHeaderBo;
import net.realsee.domain.wcs.work.vo.WcsOrderHeaderVo;
import net.realsee.framework.core.domain.PageQuery;
import net.realsee.framework.core.page.TableDataInfo;
import net.realsee.gcl.service.IGclMesService;
import net.realsee.mapper.wcs.work.WcsOrderHeaderMapper;
import net.realsee.service.wcs.rcs.hik.IHikV4Service;
import net.realsee.service.wcs.work.IWcsOrderHeaderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 单据头Service业务层处理
 *
 * @author realsee
 * @date 2023-08-11
 */
@RequiredArgsConstructor
@Service
public class WcsOrderHeaderServiceImpl extends ServiceImpl<WcsOrderHeaderMapper, WcsOrderHeader> implements IWcsOrderHeaderService {

    private final WcsOrderHeaderMapper baseMapper;

    /**
     * 查询单据头
     */
    @Override
    public WcsOrderHeaderVo selectVoById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询单据头列表
     */
    @Override
    public TableDataInfo<WcsOrderHeaderVo> selectVoPage(WcsOrderHeaderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<WcsOrderHeader> lqw = buildVoQueryWrapper(bo);
        Page<WcsOrderHeaderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询单据头列表
     */
    @Override
    public List<WcsOrderHeaderVo> selectVoList(WcsOrderHeaderBo bo) {
        LambdaQueryWrapper<WcsOrderHeader> lqw = buildVoQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<WcsOrderHeader> buildVoQueryWrapper(WcsOrderHeaderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<WcsOrderHeader> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, WcsOrderHeader::getId, bo.getId());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), WcsOrderHeader::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getOrderType() != null, WcsOrderHeader::getOrderType, bo.getOrderType());
        lqw.eq(StringUtils.isNotBlank(bo.getTaskType()), WcsOrderHeader::getTaskType, bo.getTaskType());
        lqw.eq(StringUtils.isNotBlank(bo.getFacility()), WcsOrderHeader::getFacility, bo.getFacility());
        lqw.eq(StringUtils.isNotBlank(bo.getWorkshop()), WcsOrderHeader::getWorkshop, bo.getWorkshop());
        lqw.eq(StringUtils.isNotBlank(bo.getSourceClass()), WcsOrderHeader::getSourceClass, bo.getSourceClass());
        lqw.eq(StringUtils.isNotBlank(bo.getSourceAppCode()), WcsOrderHeader::getSourceAppCode, bo.getSourceAppCode());
        lqw.eq(StringUtils.isNotBlank(bo.getSourceTaskCode()), WcsOrderHeader::getSourceTaskCode, bo.getSourceTaskCode());
        lqw.eq(bo.getPriority() != null, WcsOrderHeader::getPriority, bo.getPriority());
        lqw.eq(bo.getSourceCreateOn() != null, WcsOrderHeader::getSourceCreateOn, bo.getSourceCreateOn());
        lqw.eq(bo.getRequiredTime() != null, WcsOrderHeader::getRequiredTime, bo.getRequiredTime());
        lqw.eq(bo.getOrderStatus() != null, WcsOrderHeader::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getParOrderNo()), WcsOrderHeader::getParOrderNo, bo.getParOrderNo());
        lqw.eq(StringUtils.isNotBlank(bo.getExecOrderNo()), WcsOrderHeader::getExecOrderNo, bo.getExecOrderNo());
        lqw.eq(StringUtils.isNotBlank(bo.getVehicleType()), WcsOrderHeader::getVehicleType, bo.getVehicleType());
        lqw.eq(StringUtils.isNotBlank(bo.getEqptType()), WcsOrderHeader::getEqptType, bo.getEqptType());
        lqw.eq(StringUtils.isNotBlank(bo.getVehicleNo()), WcsOrderHeader::getVehicleNo, bo.getVehicleNo());
        lqw.eq(bo.getStartTime() != null, WcsOrderHeader::getStartTime, bo.getStartTime());
        lqw.eq(bo.getCompletionTime() != null, WcsOrderHeader::getCompletionTime, bo.getCompletionTime());
        lqw.eq(StringUtils.isNotBlank(bo.getMessage()), WcsOrderHeader::getMessage, bo.getMessage());
        lqw.eq(bo.getProgressStatus() != null, WcsOrderHeader::getProgressStatus, bo.getProgressStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getTaskTemp()), WcsOrderHeader::getTaskTemp, bo.getTaskTemp());
        lqw.eq(StringUtils.isNotBlank(bo.getFuid()), WcsOrderHeader::getFuid, bo.getFuid());
        lqw.eq(bo.getTextId() != null, WcsOrderHeader::getTextId, bo.getTextId());
        lqw.eq(bo.getRefrenceId() != null, WcsOrderHeader::getRefrenceId, bo.getRefrenceId());
        lqw.eq(bo.getUnitId() != null, WcsOrderHeader::getUnitId, bo.getUnitId());
        lqw.eq(bo.getDelFlag() != null, WcsOrderHeader::getDelFlag, bo.getDelFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), WcsOrderHeader::getCreateBy, bo.getCreateBy());
        lqw.eq(bo.getCreateTime() != null, WcsOrderHeader::getCreateTime, bo.getCreateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), WcsOrderHeader::getUpdateBy, bo.getUpdateBy());
        lqw.eq(bo.getUpdateTime() != null, WcsOrderHeader::getUpdateTime, bo.getUpdateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getDeleteBy()), WcsOrderHeader::getDeleteBy, bo.getDeleteBy());
        lqw.eq(bo.getDeleteTime() != null, WcsOrderHeader::getDeleteTime, bo.getDeleteTime());
        lqw.eq(bo.getRowVersionStamp() != null, WcsOrderHeader::getRowVersionStamp, bo.getRowVersionStamp());
        lqw.eq(StringUtils.isNotBlank(bo.getRemark()), WcsOrderHeader::getRemark, bo.getRemark());
        lqw.orderByDesc(WcsOrderHeader::getId);
        return lqw;
    }

    /**
     * 新增单据头
     */
    @Override
    public Boolean insertByBo(WcsOrderHeaderBo bo) {
        WcsOrderHeader add = BeanUtil.toBean(bo, WcsOrderHeader.class);
        return this.save(add);
    }

    /**
     * 修改单据头
     */
    @Override
    public Boolean updateByBo(WcsOrderHeaderBo bo) {
        WcsOrderHeader update = BeanUtil.toBean(bo, WcsOrderHeader.class);
        return this.updateById(update);
    }

    /**
     * 批量删除单据头
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return this.removeBatchByIds(ids);
    }

    /**
     * 通过订单号和订单类型查询
     */
    @Override
    public WcsOrderHeader getByOrderNoAndOrderType(String orderNo, Long orderType) {
        return this.lambdaQuery()
            .eq(WcsOrderHeader::getOrderNo, orderNo)
            .eq(WcsOrderHeader::getOrderType, orderType)
            .last("limit 1")
            .one();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean cancel(String orderNo) {
        // 更新数据库
        WcsOrderHeader orderHeader = this.getByOrderNoAndOrderType(orderNo, OrderTypeEnums.UP_DOWN.getCode());
        orderHeader.setOrderStatus(OrderStatusEnums.CANCEL.getCode());
        orderHeader.setCompletionTime(DateUtil.date());
        this.updateById(orderHeader);

        // RCS取消任务
        HikRcsOperateResult hikRcsOperateResult = SpringUtils.getBean(IHikV4Service.class).taskCancel(orderHeader.getOrderNo());
        if (ObjectUtil.isNull(hikRcsOperateResult)) {
            // 下发失败
            throw new ServiceException("调用RCS任务取消失败");
        }
        if (!hikRcsOperateResult.isSuccess()) {
            // 执行失败
            throw new ServiceException(hikRcsOperateResult.getMessage());
        }
        // 在MES中任务取消
        SpringUtils.getBean(IGclMesService.class).taskCancelToMes(orderNo);
        return true;
    }

    /**
     * 查询出处于等待点位上的任务集合
     */
    @Override
    public List<WcsOrderHeader> listWaitingTask() {
        return this.lambdaQuery()
            .eq(WcsOrderHeader::getOrderStatus, OrderStatusEnums.HANG_UP.getCode())
            .eq(WcsOrderHeader::getOrderType, OrderTypeEnums.UP_DOWN.getCode())
            .orderByAsc(WcsOrderHeader::getId)
            .list();
    }

    /**
     * 任务是否已经完结
     */
    @Override
    public boolean taskIsFinished(String taskCode) {
        WcsOrderHeader orderHeader = this.getByOrderNoAndOrderType(taskCode, OrderTypeEnums.UP_DOWN.getCode());
        return ObjectUtil.isNull(orderHeader)
            || ObjectUtil.equal(orderHeader.getOrderStatus(), OrderStatusEnums.COMPLETE.getCode())
            || ObjectUtil.equal(orderHeader.getOrderStatus(), OrderStatusEnums.CANCEL.getCode())
            || ObjectUtil.equal(orderHeader.getOrderStatus(), OrderStatusEnums.CLOSE.getCode())
            || ObjectUtil.equal(orderHeader.getOrderStatus(), OrderStatusEnums.FAILED.getCode());
    }
}
